//
//  NetManager.swift
//  网络请求管理
//
//  Created by chen on 2025/5/1.
//
import SwiftUI

/// 网络请求管理器
public class NetManager {
    
    public static let shared = NetManager(env: .dtk)
    
    public static let server = NetManager(env: .server)
    
    /// 环境配置
    private let env: NetEnv
    
    /// 错误处理
    private let netHandler: NetHandler
    
    /// 请求拦截器
    private let interceptor: NetInterceptor
    
    // 修改 init 为 public
    public init(
        env: NetEnv,
        netHandler: NetHandler = DefaultNetHandler(),
        interceptor: NetInterceptor = DefaultNetInterceptor()
    ) {
        self.env = env
        self.netHandler = netHandler
        self.interceptor = interceptor
    }
    
    /// 构建请求
    /// - Parameters:
    ///   - apiPath: 接口地址
    ///   - queryParam: 请求头参数
    ///   - bodyParam: 请求体参数
    /// - Returns: 返回请求对象
    private func makeRequest(_ apiPath: ApiPath,_ queryParam:[String: Any]?,_ bodyParam: Any?) throws -> URLRequest {
        var components = URLComponents(string: "\(env.rawValue)\(apiPath.rawValue)")
        // 将字典参数转换为URLQueryItem
        if var queryParam = queryParam {
            if NetEnv.dtk == env {
                queryParam["appKey"] = ApiKey.dtkAppKey.rawValue
                
                let nonce = SignUtil.getRandom6BitString()
                queryParam["nonce"] = nonce
                
                let timer = TimeUtils.getCurrentTimestamp()
                queryParam["timer"] = timer
                
                let signRan = SignUtil.getDTKSignature(appKey: ApiKey.dtkAppKey.rawValue,
                                                       appSecret: ApiKey.dtkAppSecret.rawValue,
                                                       timer: timer,
                                                       nonce: nonce)
                queryParam["signRan"] = signRan
            }
            
            components?.queryItems = queryParam.map { key, value in
                URLQueryItem(name: key, value: "\(value)")
            }
        }
        guard let url = components?.url else {
            throw NetError.invalidURL
        }
        return interceptor.beforeRequest(URLRequest(url: url), queryParam, bodyParam)
    }
    
    /// json对象处理
    /// - Parameters:
    ///   - type: 数据类型
    ///   - data: 响应数据
    /// - Returns: 转化的对象
    private func jsonObjectParse<R: Codable>(_ type: R.Type, _ data: Data) throws -> R {
        let decoder = JSONDecoder()
        let result = try decoder.decode(Result<R>.self, from: data)
        
        guard result.code == 200 || result.code == 1 || result.code == 0 else {
            throw NetError.bizError(result.code, result.msg)
        }
        
        guard let resp = result.data else {
            throw NetError.jsonParseError
        }
        return resp
    }
    
    /// json数组处理
    /// - Parameters:
    ///   - type: 数据类型
    ///   - data: 响应数据
    /// - Returns: 转化的对象
    private func jsonArrayParse<R: Codable>(_ type: R.Type, _ data: Data) throws -> [R] {
        let decoder = JSONDecoder()
        let result = try decoder.decode(Result<[R]>.self, from: data)
        
        guard result.code == 200 || result.code == 1 || result.code == 0 else {
            throw NetError.bizError(result.code, result.msg)
        }
        
        guard let resp = result.data else {
            throw NetError.jsonParseError
        }
        return resp
    }
    
    private func jsonArrayResult<R: Codable>(_ type: R.Type, _ data: Data) throws -> Result<[R]> {
        let decoder = JSONDecoder()
        let result = try decoder.decode(Result<[R]>.self, from: data)
        
        guard result.code == 200 || result.code == 1 || result.code == 0 else {
            throw NetError.bizError(result.code, result.msg)
        }
        
        return result
    }
    
    /// 无响应处理
    /// - Parameter data: 响应数据
    private func commonResultParse(_ data: Data) throws {
        let decoder = JSONDecoder()
        let result = try decoder.decode(ResultNoData.self, from: data)
        
        guard result.code == 200 || result.code == 1 || result.code == 0 else {
            throw NetError.bizError(result.code, result.msg)
        }
    }
    
    /// 字符串处理
    /// - Parameter data: 响应数据
    /// - Returns: 转化的字符串
    private func stringParse(_ data: Data) throws -> String {
        guard let string = String(data: data, encoding: .utf8) else {
            throw NetError.stringParseError
        }
        return string
    }
    
    /// 响应公共检查
    /// - Parameter response: 响应
    private func commonCheck(_ response: URLResponse) throws {
        guard let httpResponse = response as? HTTPURLResponse else {
            throw NetError.responseError
        }
        
        // 检查状态码
        guard (200...299).contains(httpResponse.statusCode) else {
            throw NetError.serverError(httpResponse.statusCode)
        }
    }
    
    /// 带参GET请求，响应结果是一个对象
    /// - Parameters:
    ///   - api: 接口请求地址
    ///   - queryParam: 请求头参数
    ///   - ok: 响应回调
    public func httpGet<R: Codable>(_ api: ApiPath, queryParam:[String: Any]?, ok:@escaping NetCallback<R>) async {
        do {
            var request = try makeRequest(api, queryParam, nil)
            request.httpMethod = "GET"
            
            let (data, response) = try await URLSession.shared.data(for: request)
            
            try commonCheck(response)
            
            interceptor.afterResponse(response, data)
            
            // 解码数据
            let result = try jsonObjectParse(R.self, data)
            await ok(result)
        } catch let error as NetError{
            netHandler.handle(error)
        } catch {
            netHandler.handle(.networkError(error))
        }
    }
    
    /// 无参GET请求，响应结果是一个对象
    /// - Parameters:
    ///   - api: 接口请求地址
    ///   - ok: 响应回调
    public func httpGet<R: Codable>(_ api: ApiPath, ok:@escaping NetCallback<R>) async {
        await httpGet(api, queryParam: nil, ok: ok)
    }
    
    /// 带参GET请求，响应是一个数组对象
    /// - Parameters:
    ///   - api: 接口请求地址
    ///   - queryParam: 请求头参数
    ///   - ok: 响应回调函数
    public func httpGetList<R: Codable>(_ api: ApiPath, queryParam:[String: Any]?, ok: @escaping NetCallbackList<R>) async {
        do {
            var request = try makeRequest(api, queryParam, nil)
            request.httpMethod = "GET"
            
            let (data, response) = try await URLSession.shared.data(for: request)
            
            try commonCheck(response)
            
            interceptor.afterResponse(response, data)
            
            // 解码数据
            let result = try jsonArrayParse(R.self, data)
            await ok(result)
        } catch let error as NetError{
            netHandler.handle(error)
        } catch {
            netHandler.handle(.networkError(error))
        }
    }
    
    public func httpGetList<R: Codable>(_ api: ApiPath, queryParam:[String: Any]?, list: @escaping NetCallbackListResult<R>) async {
        do {
            var request = try makeRequest(api, queryParam, nil)
            request.httpMethod = "GET"
            
            let (data, response) = try await URLSession.shared.data(for: request)
            
            try commonCheck(response)
            
            interceptor.afterResponse(response, data)
            
            // 解码数据
            let result = try jsonArrayResult(R.self, data)
            await list(result)
        } catch let error as NetError{
            netHandler.handle(error)
        } catch {
            netHandler.handle(.networkError(error))
        }
    }
    
    ///  无参GET请求，响应是一个数组对象
    /// - Parameters:
    ///   - api: 接口请求地址
    ///   - ok:  响应回调函数
    public func httpGetList<R: Codable>(_ api: ApiPath, ok: @escaping NetCallbackList<R>) async {
        return await httpGetList(api, queryParam: nil, ok: ok)
    }
    
    ///  带参GET请求，无响应处理
    /// - Parameters:
    ///   - api: 接口请求地址
    ///   - queryParam: 请求头参数
    public func httpGet(_ api: ApiPath, queryParam:[String: Any]?) async {
        do {
            var request = try makeRequest(api, queryParam, nil)
            request.httpMethod = "GET"
            
            let (data, response) = try await URLSession.shared.data(for: request)
            
            try commonCheck(response)
            
            interceptor.afterResponse(response, data)
            
            try commonResultParse(data)
        } catch let error as NetError{
            netHandler.handle(error)
        } catch {
            netHandler.handle(.networkError(error))
        }
    }
    
    /// 无参GET请求，无响应处理
    /// - Parameters:
    ///   - api: 接口请求地址
    public func httpGet(_ api: ApiPath) async {
        await httpGet(api, queryParam: nil)
    }
    
    /// 带参数POST请求，响应是一个对象
    /// - Parameters:
    ///   - api: 接口请求地址
    ///   - queryParam: 请求头参数
    ///   - bodyParam: 请求体参数
    ///   - ok: 响应回调函数
    public func httpPost<T: Codable, R: Codable>(_ api: ApiPath, queryParam:[String: Any]?, bodyParam: T, ok: @escaping NetCallback<R>) async {
        do {
            var request = try makeRequest(api, queryParam, bodyParam)
            request.httpMethod = "POST"
            request.addValue("application/json", forHTTPHeaderField: "Content-Type")
            
            let jsonData = try JSONEncoder().encode(bodyParam)
            request.httpBody = jsonData
            
            let (data, response) = try await URLSession.shared.data(for: request)
            
            try commonCheck(response)
            
            interceptor.afterResponse(response, data)
            
            // 解码数据
            let result = try jsonObjectParse(R.self, data)
            await ok(result)
        } catch let error as NetError{
            netHandler.handle(error)
        } catch {
            netHandler.handle(.networkError(error))
        }
    }
    
    /// 带参POST请求，响应是一个对象
    /// - Parameters:
    ///   - api: 接口请求地址
    ///   - bodyParam: 请求体参数
    ///   - ok: 响应回调函数
    public func httpPost<T: Codable, R: Codable>(_ api: ApiPath, bodyParam: T, ok: @escaping NetCallback<R>) async {
        return await httpPost(api, queryParam: nil, bodyParam: bodyParam, ok: ok)
    }
    
    /// 带参POST请求，响应是一个对象
    /// - Parameters:
    ///   - api: 接口请求地址
    ///   - queryParam: 请求头参数
    ///   - ok: 响应回调函数
    public func httpPost<R: Codable>(_ api: ApiPath, queryParam:[String: Any]?, ok: @escaping NetCallback<R>) async {
        do {
            var request = try makeRequest(api, queryParam, nil)
            request.httpMethod = "POST"
            
            let (data, response) = try await URLSession.shared.data(for: request)
            
            try commonCheck(response)
            
            interceptor.afterResponse(response, data)
            
            // 解码数据
            let result = try jsonObjectParse(R.self, data)
            await ok(result)
        } catch let error as NetError{
            netHandler.handle(error)
        } catch {
            netHandler.handle(.networkError(error))
        }
    }
    
    public func httpPost(_ api: ApiPath, queryParam:[String: Any]?) async {
        do {
            var request = try makeRequest(api, queryParam, nil)
            request.httpMethod = "POST"
            
            let (data, response) = try await URLSession.shared.data(for: request)
            
            try commonCheck(response)
            
            interceptor.afterResponse(response, data)
            
            try commonResultParse(data)
        } catch let error as NetError{
            netHandler.handle(error)
        } catch {
            netHandler.handle(.networkError(error))
        }
    }
    
    public func httpPost(_ api: ApiPath, queryParam:[String: Any]?, ok: @escaping NetCallbackVoid) async {
        do {
            var request = try makeRequest(api, queryParam, nil)
            request.httpMethod = "POST"
            
            let (data, response) = try await URLSession.shared.data(for: request)
            
            try commonCheck(response)
            
            interceptor.afterResponse(response, data)
            
            try commonResultParse(data)
            
            await ok()
        } catch let error as NetError{
            netHandler.handle(error)
        } catch {
            netHandler.handle(.networkError(error))
        }
    }
    
    public func httpPost(_ api: ApiPath, ok: @escaping NetCallbackVoid) async {
        return await httpPost(api, queryParam: nil, ok: ok)
    }
    
    public func httpPost<T: Codable>(_ api: ApiPath, bodyParam: T) async {
        do {
            var request = try makeRequest(api, nil, bodyParam)
            request.httpMethod = "POST"
            
            let jsonData = try JSONEncoder().encode(bodyParam)
            request.httpBody = jsonData
            
            let (data, response) = try await URLSession.shared.data(for: request)
            
            try commonCheck(response)
            
            interceptor.afterResponse(response, data)
            
            try commonResultParse(data)
        } catch let error as NetError{
            netHandler.handle(error)
        } catch {
            netHandler.handle(.networkError(error))
        }
    }
    
    public func httpPost<T: Codable>(_ api: ApiPath, bodyParam: T, ok: @escaping NetCallbackVoid) async {
        do {
            var request = try makeRequest(api, nil, bodyParam)
            request.httpMethod = "POST"
            
            let jsonData = try JSONEncoder().encode(bodyParam)
            request.httpBody = jsonData
            
            let (data, response) = try await URLSession.shared.data(for: request)
            
            try commonCheck(response)
            
            interceptor.afterResponse(response, data)
            
            try commonResultParse(data)
            
            await ok()
        } catch let error as NetError{
            netHandler.handle(error)
        } catch {
            netHandler.handle(.networkError(error))
        }
    }
    
    public func httpPost(_ api: ApiPath) async {
        return await httpPost(api, queryParam: nil)
    }
    
    /// 无参POST请求，响应是一个对象
    /// - Parameters:
    ///   - api: 接口请求地址
    ///   - ok: 响应回调函数
    public func httpPost<R: Codable>(_ api: ApiPath, ok: @escaping NetCallback<R>) async {
        return await httpPost(api, queryParam: nil, ok: ok)
    }
    
    /// 带参POST请求，响应是一个数组对象
    /// - Parameters:
    ///   - api: 接口请求地址
    ///   - queryParam: 请求头参数
    ///   - bodyParam: 请求体参数
    ///   - ok: 响应回调函数
    public func httpPostList<T: Codable, R: Codable>(_ api: ApiPath, queryParam:[String: Any]?, bodyParam: T, ok: @escaping NetCallbackList<R>) async {
        do {
            var request = try makeRequest(api, queryParam, bodyParam)
            request.httpMethod = "POST"
            
            let jsonData = try JSONEncoder().encode(bodyParam)
            request.httpBody = jsonData
            
            let (data, response) = try await URLSession.shared.data(for: request)
            
            try commonCheck(response)
            
            interceptor.afterResponse(response, data)
            
            // 解码数据
            let result = try jsonObjectParse([R].self, data)
            await ok(result)
        } catch let error as NetError{
            netHandler.handle(error)
        } catch {
            netHandler.handle(.networkError(error))
        }
    }
    
    /// 带参POST请求，响应是一个数组对象
    /// - Parameters:
    ///   - api: 接口请求地址
    ///   - bodyParam: 请求体参数
    ///   - ok: 响应回调函数
    public func httpPostList<T: Codable, R: Codable>(_ api: ApiPath, bodyParam: T, ok: @escaping NetCallbackList<R>) async {
        return await httpPostList(api, queryParam: nil, bodyParam: bodyParam, ok: ok)
    }
    
    /// 带参POST请求，响应是一个数组对象
    /// - Parameters:
    ///   - api: 接口请求地址
    ///   - queryParam: 请求头参数
    ///   - ok: 响应回调函数
    public func httpPostList<R: Codable>(_ api: ApiPath, queryParam:[String: Any]?, ok: @escaping NetCallbackList<R>) async {
        do {
            var request = try makeRequest(api, queryParam, nil)
            request.httpMethod = "POST"
            
            let (data, response) = try await URLSession.shared.data(for: request)
            
            try commonCheck(response)
            
            interceptor.afterResponse(response, data)
            
            // 解码数据
            let result = try jsonObjectParse([R].self, data)
            await ok(result)
        } catch let error as NetError{
            netHandler.handle(error)
        } catch {
            netHandler.handle(.networkError(error))
        }
    }
    
    /// 无参POST请求，响应是一个数组对象
    /// - Parameters:
    ///   - api: 接口请求地址
    ///   - ok: 响应回调函数
    public func httpPostList<R: Codable>(_ api: ApiPath, ok: @escaping NetCallbackList<R>) async {
        return await httpPostList(api, queryParam: nil, ok: ok)
    }
    
    ///  POST流式请求
    /// - Parameters:
    ///   - api: 接口请求地址
    ///   - queryParam:  请求头参数
    ///   - bodyParam: 请求体参数
    ///   - ok:  响应回调函数
    public func postStream<T: Codable>(_ api: ApiPath,
                                       queryParam:[String: Any]?,
                                       bodyParam: T,
                                       ok: @escaping NetCallbackStream) async {
        do {
            var request = try makeRequest(api, queryParam, bodyParam)
            request.httpMethod = "POST"
            
            let jsonData = try JSONEncoder().encode(bodyParam)
            request.httpBody = jsonData
            
            let (stream, response) = try await URLSession.shared.bytes(for: request)
            
            try commonCheck(response)
            
            var buffer = Data()
            for try await byte in stream {
                buffer.append(Data([byte]))
                if let chunk = String(data: buffer, encoding: .utf8), chunk.contains("\n\n") {
                    if chunk.hasPrefix("event:conversation.message.delta") {
                        let lines = chunk.split(separator: "\n")
                        var eventData = ""
                        var eventType = ""
                        for line in lines {
                            if line.hasPrefix("data:") {
                                eventData = String(line.dropFirst(5)).trimmingCharacters(in: .whitespacesAndNewlines)
                            } else if line.hasPrefix("event:") {
                                eventType = String(line.dropFirst(6)).trimmingCharacters(in: .whitespacesAndNewlines)
                            }
                        }
                        
                        //Logger.shared.info("postStream eventType:\(eventType)")
                        //Logger.shared.info("postStream eventData:\(eventData)")
                        
                        if eventType == "conversation.message.delta" {
                           ok(eventData)
                           try? await Task.sleep(nanoseconds: 80_000_000)
                        }
                    }
                    buffer.removeAll()
                }
            }
        } catch let error as NetError{
            netHandler.handle(error)
        } catch {
            netHandler.handle(.networkError(error))
        }
    }
    
    public func processURL(_ url: String, completion: @escaping ([String: String]?) async -> Void) async {
        do {
            Logger.shared.info("url:\(url)")
            var request = URLRequest(url: URL(string: url)!)
            request.httpMethod = "GET"
            
            let (_, response) = try await URLSession.shared.data(for: request)
            
            if let httpResponse = response as? HTTPURLResponse,
               let responseURL = httpResponse.url,
               let components = URLComponents(url: responseURL, resolvingAgainstBaseURL: true) {
                
                let parameters = components.queryItems?.reduce(into: [String: String]()) { result, item in
                    result[item.name] = item.value
                }
                
                await completion(parameters)
            } else {
                await completion(nil)
            }
        } catch {
            await completion(nil)
        }
    }
}
